#ifndef LIBRARY_H
#define LIBRARY_H

#define WIDTH 20

#include <map>
#include <iomanip>
#include <iostream>
#include <exception>

#include "Book_t.h"
#include "Borrower_t.h"

class Library_t{

public:
	Library_t();
	~Library_t();

	// Remove borrower from the map. If it isn't found do nothing.
	void removeBorrower(ID);

	// Insert new borrower to the map (by ID). If it existed before do nothing.
	void addBorrower(ID, Name=string("John Doe"));

	// Returns null if the borrower isn't found.
	Borrower_t const * searchBorrower(ID) const;

	unsigned int numAvailableCopies(Book_t const *) const;

	// Inserts the new book with it's given number of copies.
	// If book with given ISBN exists already the number of copies will be added to it.
	// If someone is waiting for the new copy then the copy will automatically be borrowed. 
	void addNewCopies(ISBN, unsigned int, Name=string("N/A"), Author=string("N/A"));

	//Removes one copy of the given ISBN (if it exists in library). 
	// Return false otherwise or if no copies are available. 
	bool removeCopy(ISBN);

	// Removes all copies of the book with the given ISBN.
	// works only if all copies are in the library.
	bool removeAllCopies(ISBN);

	// Borrow a book with the given ISBN to the borrower with given ID.
	// Returns true iff the borrower is registered and there are enough copies.
	// Returns false otherwise.
	bool borrowBook(ID, ISBN); 

	// Return a copy borrowed by the borrower and borrow it again if someone's waiting for it.
	// Returns true if the borrower is registered and in possesion of the specified book.
	// Returns false otherwise.
	bool returnBook(ID, ISBN);
	
	void printBookReport(ISBN) const;
	void printBorrowerReport(ID) const;

protected:
	map<ISBN,Book_t*>* book_map;
	map<ISBN,Borrower_t*>* borrower_map;

private:


};

ostream& allign(ostream& os);
ostream& operator<<(ostream& , const Book_t&); 
ostream& operator<<(ostream& , const Borrower_t&); 

#endif